package com.spzx.cart.service.impl;

import com.spzx.cart.api.domain.CartInfo;
import com.spzx.cart.service.ICartService;
import com.spzx.common.core.constant.HttpStatus;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.context.SecurityContextHolder;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.api.domain.ProductSku;
import com.spzx.product.api.domain.vo.SkuPrice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CartServiceImpl implements ICartService {

    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    RemoteProductService remoteProductService;

    private static String getCartKey(Long userId){
        return "user:cart:" + userId;
    }

    @Override
    public void addToCart(Long skuId, Integer skuNum) {
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        String hashKey = skuId.toString();
        BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(cartKey);

        if(boundHashOperations.hasKey(hashKey)){ //缓存中有数据,不是首次添加到购物车
            CartInfo cartInfo = (CartInfo) boundHashOperations.get(hashKey);
            int total = cartInfo.getSkuNum()+skuNum;
            int num = total>99 ? 99:total;
            if(total < 0){
                num = 1;
            }
            cartInfo.setSkuNum(num);
            cartInfo.setUpdateTime(new Date()); //设置修改时间
            boundHashOperations.put(hashKey,cartInfo);
        }else{ //首次添加购物车
            //商品种类不能超过50种
            Long size = boundHashOperations.size(); //统计键值对数量
            if(size > 49){
                throw new ServiceException("购物车种类不能超过50");
            }

            CartInfo cartInfo = new CartInfo();
            cartInfo.setUserId(userId);
            cartInfo.setSkuId(skuId);

            //远程调用服务
            R<ProductSku> productSkuR = remoteProductService.getProductSku(skuId, SecurityConstants.INNER);
            if(productSkuR.getCode()!= HttpStatus.SUCCESS){
                throw new ServiceException("");
            }
            cartInfo.setCartPrice(productSkuR.getData().getSalePrice());
            cartInfo.setSkuPrice(productSkuR.getData().getSalePrice());
            cartInfo.setSkuNum(1); //首次添加购物车,默认数量=1
            cartInfo.setCreateTime(new Date()); //首次设置创建时间
            cartInfo.setSkuName(productSkuR.getData().getSkuName());
            cartInfo.setThumbImg(productSkuR.getData().getThumbImg());
            cartInfo.setIsChecked(1);

            boundHashOperations.put(hashKey,cartInfo);
        }

    }

    @Override
    public List<CartInfo> getCartList() {
        //获取当前用户id
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        //从缓存中取数据
        List<CartInfo> cartInfoList = redisTemplate.opsForHash().values(cartKey);
        //如果没有数据
        if(CollectionUtils.isEmpty(cartInfoList)){
            return new ArrayList<>();
        }
        //按照时间倒序排序
        List<CartInfo> sortCartInfoList = cartInfoList.stream().sorted((o1, o2) ->
                o2.getCreateTime().compareTo(o1.getCreateTime())
        ).collect(Collectors.toList());

        //获取skuId列表
        List<Long> skuIdList = sortCartInfoList.stream().map(CartInfo::getSkuId).toList();
        //通过skuid获取最新价格
        R<List<SkuPrice>> skuPriceListR = remoteProductService.getSkuPriceList(skuIdList, SecurityConstants.INNER);
        //如果降级处理,抛出异常
        if(skuPriceListR.getCode() == R.FAIL){
            throw new ServiceException(skuPriceListR.getMsg());
        }
        Map<Long, BigDecimal> skuIdToPriceMap = skuPriceListR.getData().stream().collect(Collectors.toMap(
                SkuPrice::getSkuId,
                SkuPrice::getSalePrice
        ));
        //设置实时价格
        sortCartInfoList.forEach(o->{
            o.setSkuPrice(skuIdToPriceMap.get(o.getSkuId()));
        });

        return sortCartInfoList;
    }

    @Override
    public void delCartInfo(Long skuId) {
        Long userId = SecurityContextHolder.getUserId();
        //获取缓存对象
        BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(getCartKey(userId));
        boundHashOperations.delete(skuId.toString());
    }

    @Override
    public void updateCartStatus(Long skuId, Integer isChecked) {
        //获取当前用户id
        Long userId = SecurityContextHolder.getUserId();
        BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(getCartKey(userId));
        if(boundHashOperations.hasKey(skuId.toString())){
            CartInfo cartInfo =(CartInfo) boundHashOperations.get(skuId.toString());
            cartInfo.setIsChecked(isChecked);
            //传回缓存
            boundHashOperations.put(skuId.toString(),cartInfo);
        }
    }

    @Override
    public void allCheckCart(Integer isChecked) {
        Long userId = SecurityContextHolder.getUserId();
        //从缓存中取数据
        BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(getCartKey(userId));
        List<CartInfo> cartInfoList = boundHashOperations.values();
        cartInfoList.forEach(item ->{
            CartInfo cartInfo =(CartInfo) boundHashOperations.get(item.getSkuId().toString());
            cartInfo.setIsChecked(isChecked);

            //更新缓存
            boundHashOperations.put(item.getSkuId().toString(),cartInfo);
        });
    }

    @Override
    public void clearCart() {
        Long userId = SecurityContextHolder.getUserId();
        //清除缓存对象
        redisTemplate.delete(getCartKey(userId));
    }

    @Override
    public List<CartInfo> getCartCheckedList(Long userId) {
        List<CartInfo> cartInfoList = new ArrayList<>();

        List<CartInfo> cartCachInfoList = redisTemplate.opsForHash().values(getCartKey(userId));
        if(!CollectionUtils.isEmpty(cartCachInfoList)){
            for (CartInfo cartInfo : cartCachInfoList) {
                //获取选中的商品
                if(cartInfo.getIsChecked().intValue() == 1){
                    cartInfoList.add(cartInfo);
                }
            }
        }
        return cartInfoList;
    }

    @Override
    public Boolean updateCartPrice(Long userId) {
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = boundHashOperations.values();
        if(!CollectionUtils.isEmpty(cartInfoList)){
            for (CartInfo cartInfo : cartInfoList) {
                if(cartInfo.getIsChecked() == 1){
                    R<SkuPrice> skuPriceR = remoteProductService.getSkuPrice(cartInfo.getSkuId(), SecurityConstants.INNER);
                    SkuPrice skuPrice = skuPriceR.getData();
                    cartInfo.setCartPrice(skuPrice.getSalePrice());
                    cartInfo.setSkuPrice(skuPrice.getSalePrice());
                    boundHashOperations.put(cartInfo.getSkuId().toString(),cartInfo);
                }
            }
        }
        return true;
    }

    @Override
    public Boolean deleteCartCheckedList(Long userId) {
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = boundHashOperations.values();
        if(!CollectionUtils.isEmpty(cartInfoList)){
            for (CartInfo cartInfo : cartInfoList) {
                if(cartInfo.getIsChecked() == 1){
                    boundHashOperations.delete(cartInfo.getSkuId().toString());
                }
            }
        }
        return true;
    }
}